//
// Created by QU on 24-6-25.
//
#include <iostream>
#include <functional>
#include <utility>
#include <memory>
#include <vector>
#include <map>
#include <set>
#include <new>
#include <thread>
#include <algorithm>
#include <array>
#include <codecvt>
#include <string>
#include <deque>
#include <locale>

using std::cout, std::cin, std::endl;

std::string utf16_to_utf8(const char16_t* utf16_str);
std::string utf32_to_utf8(const char32_t* utf32_str);

int main(int argc, const char* argv[])
{
    // 声明原生字符串字面量的语法很简单，即prefix R"delimiter(raw_ characters)delimiter"，
    // 这其中prefix和delimiter是可选部分，我们可以忽略它们，
    // 所以最简单的原生字符串字面量声明是R"(raw_characters)"。以上面的HTML字符串为例：
    char hello_world_html[] =
        R"(<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial
scale=1, user-scalable=yes">
  <title>Hello World!</title>
</head>
<body>
Hello World!
</body>
</html>
)";
    /*
    读者在这里可能会有一个疑问，如果在声明的字符串内部有一个字符组合正好是)"，这样原生字符串不就会被截断了吗？没错，如果
    出现这样的情况，编译会出错。不过，我们也不必担心这种情况，C++11标准已经考虑到了这个问题，所以有了delimiter（分隔符）
    这个元素。delimiter可以是由除括号、反斜杠和空格以外的任何源字符构成的字符序列，长度至多为16个字符。通过添加delimiter可
    以改变编译器对原生字符串字面量范围的判定，从而顺利编译带有)"的字符串
    */

    char hello_world_html2[] = R"aquawius(<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial
scale=1, user-scalable=yes">
  <title>Hello World!</title>
</head>
<body>
"(Hello World!)"
</body >
</html>
)aquawius";
    std::cout << hello_world_html2 << std::endl;


    /*
    C++11标准除了让我们能够定义char类型的原生字符串字面量外，对于wchar_t、char8_t（C++20标准开始）、char16_t和
char32_t类型的原生字符串字面量也有支持。要支持这4种字符类型，就需要用到另外一个可选元素prefix了。这里的prefix实际上
是声明4个类型字符串的前缀L、u、U和u8。char8_t utf8[] = u8R"(你好世界)"; // C++20标准开始
    */

    // char16_t utf16[] = uR"(你好世界)";
    // char32_t utf32[] = UR"(你好世界)";
    // wchar_t wstr[] = LR"(你好世界)";
    // 测试了, 能定义, 但是打印不出来.

    /*
    最后，关于原生字符串字面量的连接规则实际上和普通字符串字
    面量是一样的，唯一需要注意的是，原生字符串字面量除了能连接原
    生字符串字面量以外，还能连接普通字符串字面量。
    */

    // std::wcout << utf16 << std::endl;
    // std::wcout << utf32 << std::endl;
    // std::wcout << wstr << std::endl;

    // 将 char16_t 字符串转换为 std::string（UTF-8）


    char16_t utf16[] = uR"(你好世界)";
    char32_t utf32[] = UR"(你好世界)";
    wchar_t wstr[] = LR"(你好世界)";

    // 转换并输出 char16_t 字符串
    std::string utf16_str = utf16_to_utf8(utf16);
    std::cout << utf16_str << std::endl;

    // 转换并输出 char32_t 字符串
    std::string utf32_str = utf32_to_utf8(utf32);
    std::cout << utf32_str << std::endl;

    // 直接输出 wchar_t 字符串
    std::wcout << wstr << std::endl;

    return 0;
}

std::string utf16_to_utf8(const char16_t* utf16_str)
{
    std::u16string u16str(utf16_str);
    std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
    return convert.to_bytes(u16str);
}

// 将 char32_t 字符串转换为 std::string（UTF-8）
std::string utf32_to_utf8(const char32_t* utf32_str)
{
    std::u32string u32str(utf32_str);
    std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
    return convert.to_bytes(u32str);
}
